package com.adcc.monitoragent.jvm;

import java.lang.management.ManagementFactory;
import java.text.DecimalFormat;

import javax.management.MBeanServer;
import javax.management.ObjectName;
import javax.management.openmbean.CompositeData;

import com.adcc.monitoragent.bean.JvmMetricsBean;
import com.adcc.monitoragent.bean.JvmMetricsBean.ClassMetricsBean;
import com.adcc.monitoragent.bean.JvmMetricsBean.GCMetricsBean;
import com.adcc.monitoragent.bean.JvmMetricsBean.MemoryMetricsBean;
import com.adcc.monitoragent.bean.JvmMetricsBean.ThreadMetricsBean;

/**
 * jvm构造类
 * 
 * @author charlie
 * 
 */
public class JvmCreate {
	private static DecimalFormat df = new DecimalFormat("##############.##");

	private static long startTime = 0l;
	private static long endTime = 0l;
	private static long startCpu = 0l;
	private static long endCpu = 0l;
	private static double cpuRatio = 0.0d;
	private static String cpuRatioStr;
	private static MBeanServer mBeanServer = ManagementFactory
			.getPlatformMBeanServer();

	static {
		new Thread() {
			public void run() {
	          while (true) {
	            try {
					if (startTime == 0l || startCpu == 0l) {
					  startTime = System.currentTimeMillis();
					  startCpu = (Long)mBeanServer.getAttribute(new ObjectName("java.lang:type=OperatingSystem"), "ProcessCpuTime");
					} else if (endTime == 0l || endCpu == 0l) {
					  endTime = System.currentTimeMillis();
					  endCpu = (Long)mBeanServer.getAttribute(new ObjectName("java.lang:type=OperatingSystem"), "ProcessCpuTime");
					} else {
					  startTime = endTime;
					  startCpu = endCpu;
					  endTime = System.currentTimeMillis();
					  endCpu = (Long)mBeanServer.getAttribute(new ObjectName("java.lang:type=OperatingSystem"), "ProcessCpuTime");
					}
					cpuRatio = (Double)((endCpu - startCpu) / 1000000.0 / (endTime - startTime) / (Integer)mBeanServer.getAttribute(new ObjectName("java.lang:type=OperatingSystem"), "AvailableProcessors"));
					//计算cpu百分比
					cpuRatio = cpuRatio * 100;
					cpuRatioStr = df.format(cpuRatio) + "%";
				} catch (Exception e) {
					e.printStackTrace();
				}
	            try {
					Thread.sleep(3000);
				} catch (InterruptedException e) {
					e.printStackTrace();
				}
	          }
	        }
	      }.start();
	}
	/**
	 * 构造jvm信息
	 * 
	 * @return
	 */
	public static JvmMetricsBean create() {
		JvmMetricsBean jvb = new JvmMetricsBean();
		try {
			jvb.setStartTime((Long)(mBeanServer.getAttribute(new ObjectName("java.lang:type=Runtime"), "StartTime")));
			jvb.setJvmName(jvm());
			jvb.setClassInfo(classMetrics());
			jvb.setConcurrentMarkSweep(gcMetrics("ConcurrentMarkSweep"));
			jvb.setCpuRatio(cpuRatioStr);
			jvb.setHeapMemory(memoryMetrics("HeapMemoryUsage"));
			jvb.setNonHeapMemory(memoryMetrics("NonHeapMemoryUsage"));
			jvb.setParNew(gcMetrics("ParNew"));
			jvb.setRuntimeName(mBeanServer.getAttribute(new ObjectName("java.lang:type=Runtime"), "Name").toString());
			jvb.setThreadsInfo(threadsMetrics());
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} 
		
		return jvb;
	}
	/**
	 * jvm信息
	 * @return
	 */
	private static String jvm() {
		StringBuffer sb = new StringBuffer();
		sb.append(System.getProperty("java.vendor"));
		sb.append(" ");
		sb.append(System.getProperty("java.version"));
		sb.append(" (");
		sb.append(System.getProperty("java.vm.name"));
		sb.append(")");
		return sb.toString();
	}

	/**
	 * 获取类加载信息
	 * @return
	 * @throws Exception
	 */
	private static ClassMetricsBean classMetrics() throws Exception {
		ClassMetricsBean bean = new ClassMetricsBean();
		bean.setClassesLoaded((Integer)mBeanServer.getAttribute(new ObjectName("java.lang:type=ClassLoading"), "LoadedClassCount"));
		bean.setClassesTotalloaded((Long)mBeanServer.getAttribute(new ObjectName("java.lang:type=ClassLoading"), "TotalLoadedClassCount"));
		bean.setClassesUnloaded((Long)mBeanServer.getAttribute(new ObjectName("java.lang:type=ClassLoading"), "UnloadedClassCount"));
		return bean;
	}
	/**
	 * gc信息
	 * @param s
	 * @return
	 * @throws Exception
	 */
	private static GCMetricsBean gcMetrics(String s)throws Exception {
		GCMetricsBean bean = new GCMetricsBean();
		ObjectName objectName = null;
		if("ParNew".equals(s)) {//YoungGC
			if (mBeanServer.isRegistered(new ObjectName("java.lang:type=GarbageCollector,name=ParNew"))) {
				objectName = new ObjectName("java.lang:type=GarbageCollector,name=ParNew");
			} else if (mBeanServer.isRegistered(new ObjectName("java.lang:type=GarbageCollector,name=Copy"))) {
				objectName = new ObjectName("java.lang:type=GarbageCollector,name=Copy");
			} else {
				objectName = new ObjectName("java.lang:type=GarbageCollector,name=PS Scavenge");
			}
		} else {//FullGC
			if (mBeanServer.isRegistered(new ObjectName("java.lang:type=GarbageCollector,name=ConcurrentMarkSweep"))) {
				objectName = new ObjectName("java.lang:type=GarbageCollector,name=ConcurrentMarkSweep");
			} else if (mBeanServer.isRegistered(new ObjectName("java.lang:type=GarbageCollector,name=MarkSweepCompact"))) {
				objectName = new ObjectName("java.lang:type=GarbageCollector,name=MarkSweepCompact");
			} else {
				objectName = new ObjectName("java.lang:type=GarbageCollector,name=PS MarkSweep");
			}

		}
		bean.setCount((Long)mBeanServer.getAttribute(objectName, "CollectionCount"));
		bean.setTime((Long)mBeanServer.getAttribute(objectName, "CollectionTime"));
		return bean;
	}
	/**
	 * 获取线程信息
	 * @return
	 * @throws Exception
	 */
	private static ThreadMetricsBean threadsMetrics() throws Exception {
		ThreadMetricsBean bean = new ThreadMetricsBean();
		bean.setThreadsCurrent((Integer)mBeanServer.getAttribute(new ObjectName("java.lang:type=Threading"), "ThreadCount"));
		bean.setThreadsDaemon((Integer)mBeanServer.getAttribute(new ObjectName("java.lang:type=Threading"), "DaemonThreadCount"));
		bean.setThreadsPeak((Integer)mBeanServer.getAttribute(new ObjectName("java.lang:type=Threading"), "PeakThreadCount"));
		bean.setThreadsTotal((Long)mBeanServer.getAttribute(new ObjectName("java.lang:type=Threading"), "TotalStartedThreadCount"));
		return bean;
	}
	/**
	 * 获取内存信息
	 * @param s
	 * @return
	 * @throws Exception
	 */
	private static MemoryMetricsBean memoryMetrics(String s) throws Exception {
		MemoryMetricsBean bean = new MemoryMetricsBean();
		CompositeData data = (CompositeData)mBeanServer.getAttribute(new ObjectName("java.lang:type=Memory"), s);
		bean.setAlloc((Long)data.get("committed"));
		bean.setMax((Long)data.get("max"));
		bean.setUsed((Long)data.get("used"));
		return bean;
	}
	
	public static void main(String[] args) throws Exception {
		while(true) {
			double b = 100;
			for (int i = 1; i < 100000000; i++) {
				b = b / i ;
			}
			JvmMetricsBean bean = create();
			System.out.println(bean);
			Thread.sleep(500);
		}
	}
}
